package com.sright.bcard.user.biz.manager.impl;

import com.sright.bcard.common.biz.manager.ContentCheckManager;
import com.sright.bcard.common.service.share.enums.EnterpriseStatusEnum;
import com.sright.bcard.common.service.share.enums.FirstLoginEnum;
import com.sright.bcard.common.service.share.enums.SourceTypeEnum;
import com.sright.bcard.common.service.share.exception.base.BusinessErrorException;
import com.sright.bcard.common.service.share.exception.code.BusinessCode;
import com.sright.bcard.common.service.share.utils.*;
import com.sright.bcard.enterprise.dal.dao.CompanyDAO;
import com.sright.bcard.enterprise.dal.dao.EnterpriseDAO;
import com.sright.bcard.enterprise.dal.entity.CompanyDO;
import com.sright.bcard.enterprise.dal.entity.EnterpriseDO;
import com.sright.bcard.user.biz.manager.AuthManager;
import com.sright.bcard.user.dal.dao.AdminDAO;
import com.sright.bcard.common.service.share.dto.user.RegisterDTO;
import com.sright.bcard.user.dal.entity.AdminDO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author peter
 * @description
 * @date 2020/5/22
 */
@Service
@Slf4j
public class AuthManagerImpl implements AuthManager {

    @Autowired
    private AdminDAO adminDAO;

    @Autowired
    private EnterpriseDAO enterpriseDAO;

    @Autowired
    private ContentCheckManager contentCheckManager;

    @Autowired
    private CompanyDAO companyDAO;

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Long register(RegisterDTO dto) throws ParseException {
        if (StringUtils.isEmpty(dto.getUsername()) || StringUtils.isEmpty(dto.getPassword())) {
            throw new BusinessErrorException(BusinessCode.PARAM_ERROR);
        }
        //新增敏感词审核
        List<String> contentList = new LinkedList<>();
        if (StringUtils.isNotEmpty(dto.getContacts())) {
            contentList.add(dto.getContacts());
        }
        if (StringUtils.isNotEmpty(dto.getName())) {
            contentList.add(dto.getName());
        }
        if (StringUtils.isNotEmpty(dto.getDepartment())) {
            contentList.add(dto.getDepartment());
        }
        if (StringUtils.isNotEmpty(dto.getJob())) {
            contentList.add(dto.getJob());
        }
        if (CollectionUtils.isNotEmpty(contentList)) {
            String checkResult = contentCheckManager.textCheck(contentList,null, SourceTypeEnum.APPLET.getValue());
            if (checkResult.equals("block")) {
                throw new BusinessErrorException(BusinessCode.CONTAIN_SENSITIVE_WORDS);
            }
        }
        List<AdminDO> adminList = adminDAO.selectByUserName(dto.getUsername());
        log.info("AuthManager.register adminList : {}", adminList);
        if (adminList != null && adminList.size() > 0) {
            throw new BusinessErrorException(BusinessCode.ACCOUNT_EXIST);
        }
        //添加enterprise
        EnterpriseDO enterpriseDO = new EnterpriseDO();
        DataConvertUtils.convertDTO2DO(dto, enterpriseDO);
        Long expirationAt = dto.getExpiration_at();
        if(expirationAt != null) {
            String s = DateTimeUtils.longTransStringDate(expirationAt * 1000);
            Date date = DateTimeUtils.formateTimeStart(s);
            enterpriseDO.setExpirationAt(date);
        }
        Long id = enterpriseDAO.insertSelective(enterpriseDO);
        log.info("AuthManager.register insert enterprise id is : {}", id);
        if (id == 0 || enterpriseDO.getId() == null) {
            throw new BusinessErrorException(BusinessCode.ENTERPRISE_ADD_ERROR);
        }

        //添加默认公司
        CompanyDO companyDO = new CompanyDO();
        companyDO.setEnterpriseId(id);
        companyDO.setName(dto.getName());
        companyDAO.insertSelective(companyDO);

        //添加admin
        AdminDO adminDO = new AdminDO();
        adminDO.setEnterpriseId(enterpriseDO.getId());
        adminDO.setUsername(dto.getUsername());
        //生成6位盐
        adminDO.setSalt(SaltUtils.getSalt(6));
        adminDO.setPassword(BcryptUtils.hashpw(dto.getPassword() + "&" + adminDO.getSalt()));
        adminDO.setCreatedAt(new Date());
        log.info("AuthManager.register insert adminDO value is : {}", adminDO);
        return adminDAO.insertSelective(adminDO);
    }

    @Override
    public Map<String, Object> login(String userName, String password) {
        log.info("login.userName :{},password : {}", userName, password);
        log.info("AuthManager.login.userName :{}, password:{}", userName, password);
        if (userName == null || userName.isEmpty()) {
            throw new BusinessErrorException(BusinessCode.ACCOUNT_NOT_NULL);
        }
        if (password == null || password.isEmpty()) {
            throw new BusinessErrorException(BusinessCode.PWD_NOT_NULL);
        }
        List<AdminDO> list = adminDAO.selectByUserName(userName);
        log.info("AuthManager.login.adminDOList :{}", list);
        if (list == null || list.size() == 0) {
            throw new BusinessErrorException(BusinessCode.ACCOUNT_NOT_EXIST);
        }
        AdminDO adminDO = list.get(0);
        log.info("AuthManager.login.adminDO :{}", adminDO);
        if (adminDO.getEnterpriseId() == null) {
            throw new BusinessErrorException(BusinessCode.ACCOUNT_ENTERPRISE_EXCEPTION);
        }
        EnterpriseDO enterpriseDO = enterpriseDAO.selectById(adminDO.getEnterpriseId());
        log.info("AuthManager.login.enterpriseDO :{}", enterpriseDO);
        if (enterpriseDO == null) {
            throw new BusinessErrorException(BusinessCode.ACCOUNT_ENTERPRISE_NOT_EXIST);
        }
        if (enterpriseDO.getStatus().equals(EnterpriseStatusEnum.FORBIDDEN.getValue())) {
            throw new BusinessErrorException(BusinessCode.ACCOUNT_FORBIDDEN);
        } else if (enterpriseDO.getStatus().equals(EnterpriseStatusEnum.OFFTIME.getValue())) {
            throw new BusinessErrorException(BusinessCode.ACCOUNT_BE_OVERDUE);
        }
        boolean passwordStatus = BcryptUtils.checkpw(password + "&" + adminDO.getSalt(),adminDO.getPassword());
        if (!passwordStatus) {
            throw new BusinessErrorException(BusinessCode.ACCOUNT_OR_PWD_ERROR);
        }
        if((new Date().getTime() - enterpriseDO.getExpirationAt().getTime()) >= 0) {
            throw new BusinessErrorException(BusinessCode.EXPERIRED_AT_TIME_OUT);
        }
        Map<String, Object> result = JWTUitls.createUserToken(String.valueOf(adminDO.getId()), adminDO.getUsername());
        // 查询是否是第一次登陆(功能改造后 默认都是第一次登陆)
        result.put("firstLogin", adminDO.getFirstlogin() == FirstLoginEnum.TRUE.getValue().intValue());
        // 查询今天是否第一次登陆
        result.put("dayFirstlogin", adminDO.getDayFirstlogin() == FirstLoginEnum.TRUE.getValue().intValue());
        // 修改登陆标识
        if(adminDO.getFirstlogin() == FirstLoginEnum.TRUE.getValue().intValue()) {
            adminDO.setFirstlogin(FirstLoginEnum.FALSE.getValue());
            adminDAO.updateSelective(adminDO);
        }
        if(adminDO.getDayFirstlogin() == FirstLoginEnum.TRUE.getValue().intValue()) {
            adminDO.setDayFirstlogin(FirstLoginEnum.FALSE.getValue());
            adminDAO.updateSelective(adminDO);
        }
        // 根据企业id查询企业信息
        // 判断过期日期是否大于当前日期
//        if(null != enterpriseDO && enterpriseDO.getExpirationAt().getTime() > new Date().getTime()) {
//            result.put("dayFirstlogin", adminDO.getDayFirstlogin() == FirstLoginEnum.TRUE.getValue().intValue());
//        }
        // 计算到期的天数
        result.put("expirationDay", DateTimeUtils.days(enterpriseDO.getExpirationAt()));

        return result;
    }

    /**
     * 通过token获取用户id
     * @param: token
     * @return java.lang.Integer
     * @author jinxuebin
     * @date 2020/5/15 5:12 下午
     */
    public Long queryUserIdByToken(String token) {
        if (StringUtils.isNotEmpty(token)) {
            return null;
        }
        return JWTUitls.validateToken(token);
    }

}
